package cn.iocoder.boot.springai001.service;

import cn.hutool.core.util.IdUtil;
import cn.iocoder.boot.springai001.entity.ChatSession;
import cn.iocoder.boot.springai001.entity.ChatSessionEntity;
import cn.iocoder.boot.springai001.repository.ChatSessionRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.messages.Message;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 会话管理服务（JPA数据库版本）
 * <p>
 * 使用 Spring Data JPA 将会话信息持久化到数据库
 * <p>
 * 配置方式：
 * 在 application.properties 中设置：
 * session.storage.type=database
 * <p>
 * 数据存储分层：
 * - ChatMemory → 存储聊天消息（Message）
 * - ChatSessionEntity → 存储会话元数据
 */
@Slf4j
@Service
@ConditionalOnProperty(name = "session.storage.type", havingValue = "database")
public class SessionServiceJpa implements ISessionService {

    private final ChatMemory chatMemory;
    private final ChatSessionRepository sessionRepository;

    public SessionServiceJpa(ChatMemory chatMemory, ChatSessionRepository sessionRepository) {
        this.chatMemory = chatMemory;
        this.sessionRepository = sessionRepository;
        log.info("✅ 使用数据库存储会话信息（JPA）");
    }

    /**
     * 创建新会话
     */
    @Override
    @Transactional
    public ChatSession createSession(String userId, String sessionName, String sessionType) {
        String sessionId = IdUtil.simpleUUID();
        
        ChatSessionEntity entity = createAndSaveSession(sessionId, userId, sessionName, sessionType, sessionId);
        
        log.info("创建会话成功（数据库）- 用户: {}, 会话: {}, 名称: {}", userId, sessionId, sessionName);
        
        return toDto(entity);
    }

    /**
     * 根据 sessionId 获取会话
     */
    @Override
    public Optional<ChatSession> getSession(String sessionId) {
        return sessionRepository.findById(sessionId)
                .filter(s -> !s.getDeleted())
                .map(this::toDto);
    }

    /**
     * 根据 userId 获取所有会话（✅ 数据库查询）
     */
    @Override
    public List<ChatSession> getUserSessions(String userId) {
        return sessionRepository.findByUserIdAndDeletedFalseOrderByLastActiveAtDesc(userId)
                .stream()
                .map(this::toDto)
                .collect(Collectors.toList());
    }

    /**
     * 根据 sessionType 获取会话（✅ 数据库查询）
     */
    @Override
    public List<ChatSession> getSessionsByType(String userId, String sessionType) {
        return sessionRepository.findByUserIdAndSessionTypeAndDeletedFalseOrderByLastActiveAtDesc(userId, sessionType)
                .stream()
                .map(this::toDto)
                .collect(Collectors.toList());
    }

    /**
     * 更新会话最后活跃时间
     */
    @Override
    @Transactional
    public void updateLastActive(String sessionId) {
        sessionRepository.findById(sessionId).ifPresent(session -> {
            session.setLastActiveAt(LocalDateTime.now());
            sessionRepository.save(session);
        });
    }

    /**
     * 获取会话的消息数量
     */
    @Override
    public int getMessageCount(String sessionId) {
        return chatMemory.get(sessionId).size();
    }

    /**
     * 获取会话的聊天记录
     */
    @Override
    public List<Message> getSessionMessages(String sessionId) {
        return getSession(sessionId)
                .map(session -> chatMemory.get(session.getConversationId()))
                .orElse(Collections.emptyList());
    }

    /**
     * 清空会话历史
     */
    @Override
    @Transactional
    public void clearSessionHistory(String sessionId) {
        getSession(sessionId).ifPresent(session -> {
            chatMemory.clear(session.getConversationId());
            log.info("清空会话历史（数据库）: {}", sessionId);
        });
    }

    /**
     * 删除会话（软删除）
     */
    @Override
    @Transactional
    public boolean deleteSession(String userId, String sessionId) {
        Optional<ChatSessionEntity> sessionOpt = sessionRepository.findById(sessionId);
        
        if (sessionOpt.isEmpty() || !userId.equals(sessionOpt.get().getUserId())) {
            log.warn("会话不存在或用户不匹配: {}", sessionId);
            return false;
        }

        ChatSessionEntity session = sessionOpt.get();
        
        // 清空聊天记忆
        chatMemory.clear(session.getConversationId());

        // 软删除
        session.setDeleted(true);
        sessionRepository.save(session);

        log.info("删除会话成功（数据库）- 用户: {}, 会话: {}", userId, sessionId);
        return true;
    }

    /**
     * 置顶会话
     */
    @Override
    @Transactional
    public void pinSession(String sessionId, boolean pinned) {
        sessionRepository.findById(sessionId).ifPresent(session -> {
            session.setPinned(pinned);
            sessionRepository.save(session);
        });
    }

    /**
     * 搜索会话（✅ 数据库查询）
     */
    @Override
    public List<ChatSession> searchSessions(String userId, String keyword) {
        return sessionRepository.searchBySessionName(userId, keyword)
                .stream()
                .map(this::toDto)
                .collect(Collectors.toList());
    }

    /**
     * 获取活跃会话（✅ 数据库查询）
     */
    @Override
    public List<ChatSession> getRecentActiveSessions(String userId, int limit) {
        return sessionRepository.findRecentSessions(userId)
                .stream()
                .limit(limit)
                .map(this::toDto)
                .collect(Collectors.toList());
    }

    /**
     * 统计信息（✅ 数据库查询）
     */
    @Override
    public Map<String, Object> getUserStatistics(String userId) {
        long totalSessions = sessionRepository.countByUserIdAndDeletedFalse(userId);
        
        List<ChatSession> sessions = getUserSessions(userId);
        int totalMessages = sessions.stream()
                .mapToInt(s -> getMessageCount(s.getConversationId()))
                .sum();

        // 按类型统计
        List<Object[]> typeCountList = sessionRepository.countByUserIdGroupByType(userId);
        Map<String, Long> typeCount = typeCountList.stream()
                .collect(Collectors.toMap(
                        arr -> (String) arr[0],
                        arr -> (Long) arr[1]
                ));

        // 最近7天活跃会话数
        LocalDateTime threshold = LocalDateTime.now().minusDays(7);
        long activeCount = sessionRepository.countByUserIdAndDeletedFalseAndLastActiveAtAfter(userId, threshold);

        return Map.of(
                "totalSessions", totalSessions,
                "totalMessages", totalMessages,
                "sessionsByType", typeCount,
                "activeSessionsLast7Days", activeCount
        );
    }

    /**
     * 根据 conversationId 获取或创建会话
     * <p>
     * 自动会话管理：如果会话已存在则更新活跃时间，不存在则自动创建
     */
    @Override
    @Transactional
    public ChatSession getOrCreateSession(String sessionId, String userId) {
        // 先尝试获取现有会话
        Optional<ChatSessionEntity> existingSessionOpt = sessionRepository.findById(sessionId);
        
        if (existingSessionOpt.isPresent() && !existingSessionOpt.get().getDeleted()) {
            // 会话已存在，更新最后活跃时间
            ChatSessionEntity existingSession = existingSessionOpt.get();
            existingSession.setLastActiveAt(LocalDateTime.now());
            sessionRepository.save(existingSession);
            
            log.debug("使用现有会话（数据库）- conversationId: {}, userId: {}", sessionId, userId);
            return toDto(existingSession);
        }

        // 会话不存在，自动创建新会话
        String autoSessionName = "自动会话-" + LocalDateTime.now().toString().substring(0, 19);
        ChatSessionEntity newSession = createAndSaveSession(sessionId, userId, autoSessionName, "general", sessionId);

        log.info("自动创建会话（数据库）- conversationId: {}, userId: {}, 名称: {}",
                sessionId, userId, autoSessionName);

        return toDto(newSession);
    }

    /**
     * 创建并保存会话（私有方法，封装重复逻辑）
     *
     * @param sessionId      会话ID
     * @param userId          用户ID
     * @param sessionName     会话名称
     * @param sessionType     会话类型
     * @param conversationId  对话ID（通常与sessionId相同）
     * @return 保存后的会话实体
     */
    private ChatSessionEntity createAndSaveSession(String sessionId, String userId, String sessionName,
                                                    String sessionType, String conversationId) {
        ChatSessionEntity entity = ChatSessionEntity.builder()
                .sessionId(sessionId)
                .userId(userId)
                .sessionName(sessionName)
                .conversationId(conversationId)
                .sessionType(sessionType)
                .createdAt(LocalDateTime.now())
                .lastActiveAt(LocalDateTime.now())
                .pinned(false)
                .deleted(false)
                .build();

        return sessionRepository.save(entity);
    }

    /**
     * Entity -> DTO 转换
     */
    private ChatSession toDto(ChatSessionEntity entity) {
        return ChatSession.builder()
                .sessionId(entity.getSessionId())
                .userId(entity.getUserId())
                .sessionName(entity.getSessionName())
                .conversationId(entity.getConversationId())
                .sessionType(entity.getSessionType())
                .createdAt(entity.getCreatedAt())
                .lastActiveAt(entity.getLastActiveAt())
                .pinned(entity.getPinned())
                .remark(entity.getRemark())
                .build();
    }
}

